Skip to content

Fix IUO type rendering so T! no longer generates T?!#354

Merged
sidepelican merged 2 commits into
uber:masterfrom
farkasseb:fix/iuo-optional-rendering
Jun 10, 2026
Merged

Fix IUO type rendering so T! no longer generates T?!#354
sidepelican merged 2 commits into
uber:masterfrom
farkasseb:fix/iuo-optional-rendering

Conversation

@farkasseb

Copy link
Copy Markdown
Contributor

Summary

Split out of #353 per review. Mockolo renders an implicitly-unwrapped optional (T!) as T?! (≈ T??), which doesn't satisfy the T! (≡ T?) protocol requirement — so the generated mock fails to conform.

// before:  public var x: Int?!   ❌ does not conform
// after:   public var x: Int!    ✅

Fixed for properties, function/subscript params & returns, and generic returns. For func/subscript handlers the synthesized closure renders ((Int?) -> Int?)? (since ! is illegal inside a closure type) while the signature keeps Int!. Inert for non-IUO types — no existing fixture output changes.

Test plan

New iuoVars / iuoFuncs compiled @Fixture mocks (conformance is compiler-enforced). swift build && swift test green.


#353 carries an extra getter-on-IUO edge test that depends on this fix, so this should land first.

🤖 Generated with Claude Code

Mockolo parses an implicitly-unwrapped optional (`Int!`) as `Optional<Int>` with
an `isIUO` flag, and `SwiftType.description` rendered its single optionality twice
— the optional-sugar case appended `?` and the `isIUO` block appended `!` —
producing `Int?!` (≈ `Int??`), which does not satisfy the `Int!` (≡ `Int?`)
protocol requirement, so the generated mock failed to conform. This was
pre-existing; no fixture exercised an IUO declaration (compiled `@Fixture` mocks
surfaced it).

- Properties: suppress the duplicate `?` for IUO in the optional-sugar case; the
  `isIUO` block still appends `!`, so the type renders `Int!`. Inert for everything
  else — plain `Int?` is unchanged, and the intentional `SomeProtocol!` force-unwrap
  backings go through the default nominal branch.
- Functions / subscripts / generic returns: `!` is illegal inside a closure type, so
  the synthesized handler closure (`((Int!) -> Int!)?`) was non-compiling. Clear
  `isIUO` on the handler's argument and return types in `toClosureType` so they
  render as plain optionals (`((Int?) -> Int?)?`, legal), while the declared
  signature keeps `Int!` and still conforms. Clearing `isIUO` is a no-op for non-IUO
  types, so no existing handler changes.

Adds compiled fixtures proving conformance: `iuoVars` (get-only + get-set) in
TestVars and `iuoFuncs` (func param/return + subscript) in TestFuncs. No existing
fixture output changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@sidepelican sidepelican left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! This makes for a good bug fix.

@sidepelican
sidepelican merged commit 1635dce into uber:master Jun 10, 2026
8 checks passed
@farkasseb
farkasseb deleted the fix/iuo-optional-rendering branch June 10, 2026 22:44
farkasseb added a commit to farkasseb/mockolo that referenced this pull request Jun 10, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants